/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package androidpos.network;

import androidpos.gui.ReaderPanel;
import androidpos.util.TransactionHandler;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author user
 */
public class Sync implements Runnable {

    private boolean stop = false;
    private int port = 5432;
    private ServerSocket ssocket;
    private Socket socket;
    private DataOutputStream dos;
    private DataInputStream dis;
    private ReaderPanel readerPanel;
    private boolean notSendThePaymentInfoYet = true;
    private boolean notSendTheBankYet = true;
    private TransactionHandler tHandler;
    public Sync(ReaderPanel readerPanel) {
        this.readerPanel = readerPanel;
        this.tHandler = readerPanel.getTransactionHandler();
    }

    public void run() {
        try {
            ssocket = new ServerSocket(port);
            socket = ssocket.accept();
            dos = new DataOutputStream(socket.getOutputStream());
            dis = new DataInputStream(socket.getInputStream());
            String msg = dis.readUTF();
            Map<String, String> dataMap = parseCommand(msg);
            if (dataMap.containsKey(Protocol.MSG_JOIN)) {
                readerPanel.setClientHost(dataMap.get(Protocol.MSG_JOIN));

                String ackCommand = genCommand(Protocol.MSG_ACK, Protocol.DATA_OK);
                dos.writeUTF(ackCommand);
                readerPanel.setSendInfoButtonEnabled(true);

                //Waiting for POS send the payment info.
                while (notSendThePaymentInfoYet)
                    if(stop){
                         return;
                    }
                readerPanel.setSendInfoButtonEnabled(false);
                
                String amount = readerPanel.getTotalPrice();
                String unit = readerPanel.getUnit();
                String paymentDetail = genCommand(Protocol.PAY_AMOUNT, amount) + genCommand(Protocol.PAY_UNIT, unit);
                dos.writeUTF(paymentDetail);

                String paymentMsg = dis.readUTF();
                Map<String, String> paymentData = parseCommand(paymentMsg);
                if (!paymentData.containsKey(Protocol.CARD_NUM) || !paymentData.containsKey(Protocol.CARD_TYPE) || !paymentData.containsKey(Protocol.CARD_SECCODE) || !paymentData.containsKey(Protocol.CARD_EXP_MONTH) || !paymentData.containsKey(Protocol.CARD_EXP_YEAR) || !paymentData.containsKey(Protocol.CARD_NAME)) {
                    disconnect();
                    return;
                }
                readerPanel.setClientName(paymentData.get(Protocol.CARD_NAME));
                readerPanel.setStartPayButtonEnabled(true);
                //Waiting for clicking the pay button
                while(notSendTheBankYet)                    
                    if(stop){
                        return;
                    }
                
                readerPanel.freezeCancelButton();
                readerPanel.setStartPayButtonEnabled(false);
                
                if (sendToTheBankAndGetTheResult()) {
                    dos.writeUTF(genCommand(Protocol.MSG_ACK, Protocol.DATA_OK));
                    tHandler.insertToTransaction(paymentData.get(Protocol.CARD_NAME), amount, unit);
                    JOptionPane.showMessageDialog(readerPanel, paymentData.get(Protocol.CARD_NAME)+" paid!");
                }
                else{
                    dos.writeUTF(genCommand(Protocol.MSG_ACK, Protocol.DATA_FAIL));                    
                    JOptionPane.showMessageDialog(readerPanel, paymentData.get(Protocol.CARD_NAME)+" fail to pay!");
                }
               
            } disconnect();
        } catch (Exception ex) {
            disconnect();
            ex.printStackTrace();
        }
    }

    public void sendPaymentInformation() {
        notSendThePaymentInfoYet = false;
    }
    public void sendToTheBank(){
        notSendTheBankYet = false;
    }
    private void disconnect(){
        try {
            if(!ssocket.isBound())
               new Socket(InetAddress.getLocalHost().getHostAddress(),port);
            ssocket.close();         
            if(socket!=null)
            {
                dis.close();
                dos.close();
                socket.close();
            }

            readerPanel.resetAll();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    public void stop(){
        stop = true;
        disconnect();
    }
    private static Map<String, String> parseCommand(String txt) {
        Map<String, String> dataMap = new HashMap<String, String>();
        String datas[] = txt.split(";");
        for (String data : datas) {
            String header = data.split(":")[0].trim();
            String msg = data.split(":")[1].trim();
            dataMap.put(header, msg);
        }
        return dataMap;
    }

    private static String genCommand(String key, String value) {
        return key + ":" + value + ";";
    }

    private boolean sendToTheBankAndGetTheResult() {
        return true;
    }
}
